#version 410

#define DEBUG

out vec3 out_Color;

uniform sampler2D u_depthTX;
uniform sampler2D u_normalTX;
uniform sampler2D u_diffuseTX;
uniform sampler2D u_miscTX;

uniform float u_Near;
uniform float u_Far;

uniform vec3 u_Up;

uniform vec3 u_bottomColor;
uniform vec3 u_topColor;

uniform int u_gbufferView;

in vec2 fs_Texcoord;

const float ambientFactor = .1f;

// Code from : http://aras-p.info/texts/CompactNormalStorage.html
vec3 unpackNormal(vec2 encNorm) {
#ifdef DEBUG
	if(encNorm.x < .000001f && encNorm.y < .00000001)
		return vec3(.0f, .0f, .0f);
#endif

	vec2 fenc = encNorm*4.0f - 2.0f;
	float f = dot(fenc, fenc);
	float g = sqrt(1.0f -.25f*f);
	return vec3(fenc*g,1.0f - .5f*f);
}

vec4 packFloatTo4x8(in float val) {
	uint a = floatBitsToInt(val);
	return vec4((bitfieldExtract(a,0,8))/256.0f,
				(bitfieldExtract(a,8,8))/256.0f,
				(bitfieldExtract(a,16,8))/256.0f,
				(bitfieldExtract(a,24,8))/256.0f);
}

float unpack4x8ToFloat(in vec4 val) {
	uint a = uint(val.x*256.0f+.5f) + 
	uint(val.y*256.0f+.5f)*256u + 
	uint(val.z*256.0f+.5f)*256u*256u+
	uint(val.w*256.0f+.5f)*256u*256u*256u;
	return uintBitsToFloat(a);
}

vec4 pack2FloatTo4x8(in vec2 val) {
	uint a = packUnorm2x16(val);
	return vec4((bitfieldExtract(a,0,8))/256.0f,
				(bitfieldExtract(a,8,8))/256.0f,
				(bitfieldExtract(a,16,8))/256.0f,
				(bitfieldExtract(a,24,8))/256.0f);
}

vec2 unpack4x8To2Float(in vec4 val) {
	uint a = uint(val.x*256.0f+.5f) + 
	uint(val.y*256.0f+.5f)*256u + 
	uint(val.z*256.0f+.5f)*256u*256u+
	uint(val.w*256.0f+.5f)*256u*256u*256u;
	return unpackUnorm2x16(a);
}

float linearizeDepth(float exp_depth, float near, float far) {
    return	(2 * near) / (far + near -  exp_depth * (far - near)); 
}

void main(void) {

	vec3 light = mix(u_bottomColor, u_topColor, (.5f + .5f*dot(unpackNormal(unpack4x8To2Float(texture(u_normalTX, fs_Texcoord))), u_Up)));

	out_Color = texture(u_diffuseTX, fs_Texcoord).rgb*light*ambientFactor;
}